1 module features.android_sdk; 2 3 import feature; 4 import commons; 5 6 Feature AndroidSDKFeature; 7 8 enum TargetAndroidSDK = 35; 9 10 11 version(Windows) enum SearchForSDK = true; 12 else version(OSX) enum SearchForSDK = true; 13 else enum SearchForSDK = false; 14 15 private bool androidSdkExists(ref Terminal t, TargetVersion ver, out ExistenceStatus status) 16 { 17 static if(SearchForSDK) 18 { 19 string androidStudioSdkPath; 20 version(OSX) 21 { 22 androidStudioSdkPath = buildNormalizedPath("~", "Library", "Android", "sdk"); 23 } 24 else version(Windows) 25 { 26 if("LOCALAPPDATA" in environment) 27 androidStudioSdkPath = buildNormalizedPath(environment["LOCALAPPDATA"], "Android", "Sdk"); 28 } 29 string sdkManagerPath = androidStudioSdkPath.buildNormalizedPath("cmdline-tools", "latest", "sdkmanager".executableExtension); 30 if(std.file.exists(sdkManagerPath)) 31 { 32 status.place = ExistenceStatus.Place.custom; 33 status.where = androidStudioSdkPath; 34 return true; 35 } 36 } 37 return false; 38 } 39 40 private string getAndroidSDKPackagesToinstall(string sdkMajorVer) 41 { 42 import std.conv:to; 43 string packages = `"build-tools;`~(sdkMajorVer)~`.0.0" `~ 44 `"extras;google;webdriver" ` ~ 45 `"platform-tools" ` ~ 46 `"platforms;android-`~to!string(sdkMajorVer)~`" `~ 47 `"sources;android-`~to!string(sdkMajorVer)~`" `; 48 49 version(Windows) 50 { 51 packages~= `"extras;intel;Hardware_Accelerated_Execution_Manager" `~ 52 `"extras;google;usb_driver" `; 53 } 54 return packages; 55 56 } 57 58 private bool installAndroidSDK(ref Terminal t, ref RealTimeConsoleInput input, TargetVersion ver, Download[] content) 59 { 60 import std.conv:to; 61 string sdkPath = buildNormalizedPath(std.file.getcwd(), "Android", "Sdk"); 62 string cmdLineTools = buildNormalizedPath(sdkPath, "cmdline-tools", "latest"); 63 64 //Rename cmdline-tools/cmdline-tools to cmdline-tools/latest 65 if(!std.file.exists(cmdLineTools)) 66 std.file.rename(buildNormalizedPath(sdkPath, "cmdline-tools", "cmdline-tools"), cmdLineTools); 67 68 t.writeln("Updating SDK manager."); 69 t.flush; 70 string sdkManagerPath = buildNormalizedPath(cmdLineTools, "bin"); 71 72 if(!makeFileExecutable(buildNormalizedPath(sdkManagerPath, "sdkmanager"))) 73 { 74 t.writelnError("Failed to set sdkmanager as executable."); 75 return false; 76 } 77 string execSdkManager = "sdkmanager "; 78 version(Posix) execSdkManager = "./sdkmanager"; 79 80 if(t.wait(spawnShell("cd "~sdkManagerPath~" && "~execSdkManager~" --install")) != 0) 81 { 82 t.writelnError("Failed on installing SDK."); 83 return false; 84 } 85 string packagesToInstall = getAndroidSDKPackagesToinstall(ver.major.to!string); 86 87 t.writelnHighlighted("Installing packages: ", packagesToInstall, " \n\t", "You may need to accept some permissions, this process may take a little bit of time."); 88 t.flush; 89 90 if(t.wait(spawnShell("cd "~sdkManagerPath~" && "~execSdkManager ~" " ~packagesToInstall)) != 0) 91 { 92 t.writelnError("Failed on installing SDK packages."); 93 return false; 94 } 95 96 string adbPath = buildNormalizedPath(sdkPath, "platform-tools", "adb"); 97 if(!makeFileExecutable(adbPath)) 98 { 99 t.writelnError("Failed to set ",adbPath," as executable."); 100 return false; 101 } 102 103 configs["androidSdkPath"] = sdkPath; 104 updateConfigFile(); 105 return true; 106 } 107 108 void initialize() 109 { 110 import std.conv:to; 111 AndroidSDKFeature = Feature( 112 "Android SDK", 113 "Required for being able to develop applications for Android", 114 ExistenceChecker(["androidSdkPath"], null, toDelegate(&androidSdkExists)), 115 Installation([Download( 116 DownloadURL( 117 windows:"https://dl.google.com/android/repository/commandlinetools-win-11076708_latest.zip", 118 linux: "https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip", 119 osx: "https://dl.google.com/android/repository/commandlinetools-mac-11076708_latest.zip" 120 ) 121 )], toDelegate(&installAndroidSDK), extractionPathList: ["$CWD/Android/Sdk/cmdline-tools"]), 122 (ref Terminal t, string where){environment["ANDROID_HOME"] = where;}, 123 VersionRange.parse(TargetAndroidSDK.to!string) 124 ); 125 } 126 void start(){}